// rabbittool
package rabbitTool

import (
	"github.com/streadway/amqp"
)

var (
	MQConn *amqp.Connection
)

type MQConnection struct {
	Conn         *amqp.Connection // RabbitMQ 连接
	Chan         *amqp.Channel    // RabbitMQ 通道
	ExchangeName string           // 交换机名
	QueueName    string           // 队列名
	RouteKey     string           // 路由名
}

/*
描述
	创建一个RabbitMQ连接Connection
参数
	uri		【string】	RabbitMQ连接uri地址
返回
	err 错误信息
*/
func Connection(uri string) error {
	var err error
	MQConn, err = amqp.Dial(uri)
	return err
}

/*
描述
	创建一个channel队列
参数
	Conn 			【*amqp.Connection】	RabbitMQ连接
	ExchangeName    【string】			交换机名
	QueueName		【string】      		队列名
	RouteKey  		【string】      		路由健
返回
	ChanApi 		【*MQConnection】	通道API链接池
	err 			【error】			错误信息
*/
func Channel(ExchangeName string, QueueName string, RouteKey string) (*MQConnection, error) {
	var (
		Chan    *amqp.Channel
		ChanApi *MQConnection
		err     error
	)
	if Chan, err = MQConn.Channel(); err != nil {
		return ChanApi, err
	}
	ChanApi = &MQConnection{
		Conn:         MQConn,
		Chan:         Chan,
		ExchangeName: ExchangeName,
		QueueName:    QueueName,
		RouteKey:     RouteKey,
	}
	return ChanApi, err
}

/*
描述
	创建一个exchange交换机
参数
	kind 			【string】	交换机类型
	durable			【bool】		是否持久化
	autoDeleted     【bool】		是否自动删除
返回
	err 			【error】	错误信息
*/
func (ChanApi *MQConnection) Exchange(kind string, durable bool, autoDeleted bool) error {
	err := ChanApi.Chan.ExchangeDeclare(
		ChanApi.ExchangeName, //交换机名
		kind,                 //类型
		durable,              // is durable
		autoDeleted,          // is auto-deleted
		false,                // is internal
		false,                // is noWait
		nil,                  //arguments
	)
	return err
}

/*
描述
	创建一个queue通道
参数
	durable			【bool】		是否持久化
	autoDeleted     【bool】		是否自动删除
返回
	err 			【error】	错误信息
*/
func (ChanApi *MQConnection) Queue(durable bool, autoDeleted bool) error {
	_, err := ChanApi.Chan.QueueDeclare(
		ChanApi.QueueName, // name
		durable,           // durable
		autoDeleted,       // delete when unused
		false,             // exclusive
		false,             // no-wait
		nil,               // arguments
	)
	return err
}

/*
描述
	交换机绑定队列
参数
	durable			【bool】		是否持久化
	autoDeleted     【bool】		是否自动删除
返回
	err 			【error】	错误信息
*/
func (ChanApi *MQConnection) Bind() error {
	err := ChanApi.Chan.QueueBind(ChanApi.QueueName, ChanApi.RouteKey, ChanApi.ExchangeName, false, nil)
	return err
}

/*
描述
	生产一条消息
参数
	message		【byte】		是否自动删除
返回
	err			【error】	错误信息
*/
func (ChanApi *MQConnection) Publish(message []byte, header amqp.Table, CorrelationId string) error {
	err := ChanApi.Chan.Publish(
		ChanApi.ExchangeName, // exchange
		ChanApi.RouteKey,     // routing key
		false,                // mandatory
		false,                // immediate
		amqp.Publishing{
			Headers:         header,
			ContentType:     "text/html",
			ContentEncoding: "",
			CorrelationId:   CorrelationId,
			Body:            []byte(message),
		},
	)
	return err
}

/*
描述
	创建消费通道来监听消费消息
参数
	consumerName		【string】		消费通道名 用于区分不同的消费者
	autoAck				【bool】			是否自动回复    true 会在收到消息后直接消费掉这条消息  false 收到消息过后需要手动消费这条消息 不然的话将回到队列中去
返回
	err			【error】	错误信息
*/
func (ChanApi *MQConnection) Consume(consumerName string, autoAck bool) (<-chan amqp.Delivery, error) {
	messageChannel, err := ChanApi.Chan.Consume(
		ChanApi.QueueName,
		consumerName,
		false, // auto-ack 是否自动回复，【自动回复表示该条队列消息已经被处理过了，消费掉了】
		false, // exclusive
		false, // no-local
		false, // no-wait
		nil,   // args
	)
	return messageChannel, err
}
